#include <stdio.h>
#include "hall.h"
#include "bldc.h"

// TIM2句柄
static TIM_HandleTypeDef htim2_speed_capture;

// 新的三霍尔联合测速变量
volatile hall_speed_capture_t g_hall_speed_capture = {
    .time_intervals = {0},
    .current_index = 0,
    .valid_count = 0,
    .last_capture_time = 0,
    .is_first_capture = 1,
    .last_valid_time = 0,
    .total_time = 0
};




/**
  * @brief  TIM2三霍尔输入捕获测速初始化
  * @param  无
  * @retval 无
  */
void hall_init(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    TIM_IC_InitTypeDef sConfigIC = {0};
    
    // 使能时钟
    __HAL_RCC_GPIOA_CLK_ENABLE();
    SPEED_CAPTURE_TIM_CLK_ENABLE();
    
    // 配置三个霍尔GPIO为复用功能
    GPIO_InitStruct.Pin = SPEED_CAPTURE_GPIO_PIN_U | SPEED_CAPTURE_GPIO_PIN_V | SPEED_CAPTURE_GPIO_PIN_W;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    GPIO_InitStruct.Alternate = SPEED_CAPTURE_GPIO_AF;
    HAL_GPIO_Init(SPEED_CAPTURE_GPIO_PORT, &GPIO_InitStruct);
    
    // TIM2基本配置
    htim2_speed_capture.Instance = SPEED_CAPTURE_TIM;
    htim2_speed_capture.Init.Prescaler = 0;                            // 不分频，使用最高精度
    htim2_speed_capture.Init.CounterMode = TIM_COUNTERMODE_UP;
    htim2_speed_capture.Init.Period = 0xFFFFFFFF;                      // 32位定时器，最大计数值
    htim2_speed_capture.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
    htim2_speed_capture.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
    
    if (HAL_TIM_Base_Init(&htim2_speed_capture) != HAL_OK)
    {
        Error_Handler();
    }
    
    if (HAL_TIM_IC_Init(&htim2_speed_capture) != HAL_OK)
    {
        Error_Handler();
    }
    
    // 配置三个通道的输入捕获，都设置为上升下降沿触发
    sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_BOTHEDGE;  // 上升下降沿都触发
    sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI;          // 直连输入
    sConfigIC.ICPrescaler = TIM_ICPSC_DIV1;                    // 不分频，每个有效沿都捕获
    sConfigIC.ICFilter = 0x03;                                 // 输入滤波，防止噪声干扰
    
    // 配置通道1 (PA0/HALL_U)
    if (HAL_TIM_IC_ConfigChannel(&htim2_speed_capture, &sConfigIC, SPEED_CAPTURE_CHANNEL_U) != HAL_OK)
    {
        Error_Handler();
    }
    
    // 配置通道2 (PA1/HALL_V)
    if (HAL_TIM_IC_ConfigChannel(&htim2_speed_capture, &sConfigIC, SPEED_CAPTURE_CHANNEL_V) != HAL_OK)
    {
        Error_Handler();
    }
    
    // 配置通道3 (PA2/HALL_W)
    if (HAL_TIM_IC_ConfigChannel(&htim2_speed_capture, &sConfigIC, SPEED_CAPTURE_CHANNEL_W) != HAL_OK)
    {
        Error_Handler();
    }
    
    // 配置NVIC中断优先级
    HAL_NVIC_SetPriority(SPEED_CAPTURE_TIM_IRQn, 1, 0);   // 高优先级，确保及时响应
    HAL_NVIC_EnableIRQ(SPEED_CAPTURE_TIM_IRQn);
    
    printf("TIM2 three-hall speed capture initialized\r\n");
}


// 纯粹的Hall传感器读取函数
uint8_t read_hall_sensors(void)
{
    uint32_t gpio_idr = GPIOA->IDR;
    
    uint8_t hall_u = (gpio_idr >> 0) & 0x01;  // PA0
    uint8_t hall_v = (gpio_idr >> 1) & 0x01;  // PA1  
    uint8_t hall_w = (gpio_idr >> 2) & 0x01;  // PA2
    
    return (hall_w << 2) | (hall_v << 1) | hall_u;
}

/**
  * @brief  启动TIM2三霍尔输入捕获测速
  * @param  无
  * @retval 无
  */
void bldc_speed_capture_start(void)
{
    // 重置测速相关变量
    bldc_speed_capture_reset();
    
    // 启动三个通道的输入捕获
    if (HAL_TIM_IC_Start_IT(&htim2_speed_capture, SPEED_CAPTURE_CHANNEL_U) != HAL_OK)
    {
        Error_Handler();
    }
    if (HAL_TIM_IC_Start_IT(&htim2_speed_capture, SPEED_CAPTURE_CHANNEL_V) != HAL_OK)
    {
        Error_Handler();
    }
    if (HAL_TIM_IC_Start_IT(&htim2_speed_capture, SPEED_CAPTURE_CHANNEL_W) != HAL_OK)
    {
        Error_Handler();
    }
    
    // 启动定时器基本功能（用于溢出检测）
    if (HAL_TIM_Base_Start_IT(&htim2_speed_capture) != HAL_OK)
    {
        Error_Handler();
    }
    
    printf("TIM2 three-hall speed capture started\r\n");
}

/**
  * @brief  停止TIM2三霍尔输入捕获测速
  * @param  无
  * @retval 无
  */
void bldc_speed_capture_stop(void)
{
    // 停止三个通道的输入捕获
    HAL_TIM_IC_Stop_IT(&htim2_speed_capture, SPEED_CAPTURE_CHANNEL_U);
    HAL_TIM_IC_Stop_IT(&htim2_speed_capture, SPEED_CAPTURE_CHANNEL_V);
    HAL_TIM_IC_Stop_IT(&htim2_speed_capture, SPEED_CAPTURE_CHANNEL_W);
    
    // 停止定时器基本功能
    HAL_TIM_Base_Stop_IT(&htim2_speed_capture);
    
    g_bldc_motor1.speed = 0;
    
    printf("TIM2 three-hall speed capture stopped\r\n");
}

/**
  * @brief  重置三霍尔测速相关变量
  * @param  无
  * @retval 无
  */
void bldc_speed_capture_reset(void)
{
    // 重置新的三霍尔测速结构
    for(int i = 0; i < HALL_STATES_PER_REV; i++)
    {
        g_hall_speed_capture.time_intervals[i] = 0;
    }
    g_hall_speed_capture.current_index = 0;
    g_hall_speed_capture.valid_count = 0;
    g_hall_speed_capture.last_capture_time = 0;
    g_hall_speed_capture.is_first_capture = 1;
    g_hall_speed_capture.last_valid_time = HAL_GetTick();
    g_hall_speed_capture.total_time = 0;
    
    // 清零定时器计数器
    __HAL_TIM_SET_COUNTER(&htim2_speed_capture, 0);
}

/**
  * @brief  获取通过三霍尔输入捕获测量的电机转速
  * @param  无
  * @retval 电机转速(RPM)
  */
uint32_t bldc_get_motor_rpm_from_capture(void)
{
    uint32_t current_time = HAL_GetTick();
    
    // 检查是否超时（电机可能已停止）
    if ((current_time - g_hall_speed_capture.last_valid_time) > (SPEED_TIMEOUT_MS))
    {
        g_bldc_motor1.speed = 0;
    }
    return g_bldc_motor1.speed;
}



/**
  * @brief  TIM2三霍尔输入捕获中断回调函数
  * @param  htim: 定时器句柄
  * @retval 无
  */
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
    if (htim->Instance == SPEED_CAPTURE_TIM)
    {
        // 检查是哪个通道触发了中断（任意霍尔状态变化都进入）
        if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1 || 
            htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2 || 
            htim->Channel == HAL_TIM_ACTIVE_CHANNEL_3)
        {
            uint32_t current_capture_time = __HAL_TIM_GET_COUNTER(htim);
            
            if (g_hall_speed_capture.is_first_capture)
            {
                // 第一次捕获，只记录时间，不计算速度，因为电机启动时的位置是随机的，它不是完整的30度变化
                g_hall_speed_capture.last_capture_time = current_capture_time;
                g_hall_speed_capture.is_first_capture = 0;
                g_bldc_motor1.speed = 0;
            }
            else
            {
                // 计算本次霍尔变化的时间间隔
                uint32_t time_interval;
                if (current_capture_time >= g_hall_speed_capture.last_capture_time)
                {
                    time_interval = current_capture_time - g_hall_speed_capture.last_capture_time;
                }
                else
                {
                    // 处理定时器溢出情况
                    time_interval = (0xFFFFFFFF - g_hall_speed_capture.last_capture_time) + current_capture_time + 1;
                }
                
                // 滑动窗口优化算法
                if (g_hall_speed_capture.valid_count < HALL_STATES_PER_REV)
                {
                    // 窗口未满，直接累加
                    g_hall_speed_capture.total_time += time_interval;
                    g_hall_speed_capture.valid_count++;
                    
                    // 窗口未满时：用已有数据推算速度，快速反馈给PID
                    if (g_hall_speed_capture.total_time > 0)
                    {
                        // 推算完整一圈时间 = (当前总时间 * 12) / 已有间隔数
                        uint32_t estimated_rev_time = (g_hall_speed_capture.total_time * HALL_STATES_PER_REV) / g_hall_speed_capture.valid_count;
                        g_bldc_motor1.speed = (uint32_t)(RPM_CALC_CONSTANT / estimated_rev_time);
                    }
                    else
                    {
                        g_bldc_motor1.speed = 0;
                    }
                }
                else
                {
                    // 窗口已满，减去旧值，加上新值（只需两次运算）
                    g_hall_speed_capture.total_time -= g_hall_speed_capture.time_intervals[g_hall_speed_capture.current_index];
                    g_hall_speed_capture.total_time += time_interval;
                    
                    // 窗口满后：用精确的完整一圈时间计算速度
                    if (g_hall_speed_capture.total_time > 0)
                    {
                        g_bldc_motor1.speed = (uint32_t)(RPM_CALC_CONSTANT / g_hall_speed_capture.total_time);
                    }
                    else
                    {
                        g_bldc_motor1.speed = 0;
                    }
                }
                
                // 存入滑动窗口
                g_hall_speed_capture.time_intervals[g_hall_speed_capture.current_index] = time_interval;
                g_hall_speed_capture.current_index = (g_hall_speed_capture.current_index + 1) % HALL_STATES_PER_REV;
                
                // 更新时间戳
                g_hall_speed_capture.last_capture_time = current_capture_time;  
            }
            g_hall_speed_capture.last_valid_time = HAL_GetTick();
        }
    }
}


/**
  * @brief  TIM2中断处理函数
  * @param  无
  * @retval 无
  */
void TIM2_IRQHandler(void)
{
    HAL_TIM_IRQHandler(&htim2_speed_capture);
}
